﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Collections.ObjectModel;

namespace Summerset.Isbndb.Subjects
{
    /// <summary>
    /// The 'subjects' collection provides information about book subjects. To retrieve corresponding books you can use 'subject_id' to search in the books collection.
    /// </summary>
    public sealed class SubjectElement : ResponseElementBase
    {
        #region Constructor + Overridden Properties

        /* Example Element:
            <SubjectData subject_id="orthodontics_examinations_questions_etc" book_count="2" marc_field="652" marc_indicator_1="" marc_indicator_2="">
                <Name>Orthodontics -- Examinations, questions, etc</Name>
            </SubjectData>
         */

        /// <summary>
        /// Initializes a new instance of the <see cref="SubjectElement"/> class.
        /// </summary>
        /// <param name="subjectElement">The xml element containing the underlying information for this instance.</param>
        public SubjectElement(XmlElement subjectElement) 
            : base(subjectElement) { }

        /// <summary>
        /// Gets the element name that is expected by the constructor of this object.
        /// If the provided element name does not match the expected element name, an exception will be thrown.
        /// </summary>
        protected override string ExpectedElementName
        {
            get { return "SubjectData"; }
        }

        #endregion
        #region Common Result Properties

        /// <summary>
        /// A string that uniquely-identifies this subject within the ISBNDB.com API.
        /// </summary>
        public string SubjectId
        {
            get { return _element.Attributes["subject_id"].Value; }
        }

        /// <summary>
        /// The number of publications in this Subject.
        /// </summary>
        public int BookCount
        {
            get { return int.Parse(_element.Attributes["book_count"].Value); }
        }

        /// <summary>
        /// Where available this represents the value corresponding to MARC standard. See http://www.loc.gov/marc/bibliographic/ecbdhome.html for details.
        /// </summary>
        public string MarcField
        {
            get { return _element.Attributes["marc_field"].Value; }
        }
        
        /// <summary>
        /// Where available this represents the value corresponding to MARC standard. See http://www.loc.gov/marc/bibliographic/ecbdhome.html for details.
        /// </summary>
        public string MarcIndicator1
        {
            get { return _element.Attributes["marc_indicator_1"].Value; }
        }
        
        /// <summary>
        /// Where available this represents the value corresponding to MARC standard. See http://www.loc.gov/marc/bibliographic/ecbdhome.html for details.
        /// </summary>
        public string MarcIndicator2
        {
            get { return _element.Attributes["marc_indicator_2"].Value; }
        }

        /// <summary>
        /// A friendly name for this subject that can be displayed to users.
        /// </summary>
        public string Name
        {
            get
            {
                var nameElement = (XmlElement)_element.SelectSingleNode("/Name");
                return nameElement.InnerText;
            }
        }

        #endregion
        #region Additional Result Properties

        /// <summary>
        /// OPTIONAL RESULT: Gets all Categorys that are relevant to this subject.        
        /// </summary>
        /// <remarks>
        /// This result set is optional and must be explicitly requested from the API.
        /// If not requested, this property will return a null reference.
        /// </remarks>
        public ReadOnlyCollection<SubjectElementCategory> Categories
        {
            get
            {
                if (_categories == null)
                    _categories = BuildChildCollection<SubjectElementCategory>("/Categories/Category");

                return _categories;
            }
        }
        ReadOnlyCollection<SubjectElementCategory> _categories;

        /// <summary>
        /// OPTIONAL RESULT: Gets additional information about this subject.
        /// </summary>
        /// <remarks>
        /// This result set is optional and must be explicitly requested from the API.
        /// If not requested, this property will return a null reference.
        /// </remarks>
        public ReadOnlyCollection<SubjectElementStructure> Structures
        {
            get
            {
                if (_structure == null)
                    _structure = BuildChildCollection<SubjectElementStructure>("/SubjectStructure/SubjectElement");

                return _structure;
            }
        }
        ReadOnlyCollection<SubjectElementStructure> _structure;

        #endregion
    }
}
